# encoding: utf-8


"""

@author: tongzhenguo

@time: 2021/5/14 下午8:57

@desc:

基本面分析
PE、PE分位点
PEG
ROE
商誉占比:并购新公司占归母所有者权益
年复合增长率

"""
import traceback
from collections import defaultdict

import baostock as bs
import pandas as pd

from const import PROJ_HOME
from date_util import now_date_fmt, now_quarter, last_n_day


class FundamentalsAnalytics(object):
    def __init__(self):
        super().__init__()
        self.start_date = last_n_day(7, "str", format="YYYY-MM-DD")
        self.end_date = now_date_fmt(fmt="YYYY-MM-DD")
        self.frequency = "d"
        self.adjustflag = "3"
        self.year = now_date_fmt(fmt="YYYY")
        self.stock_fund_dict = defaultdict(dict)

    @staticmethod
    def pe_percent(row, cols, percent):
        """计算PE各分位点
        推荐使用最近5年PE-TTM分位点或者最近10年PE-TTM分位点

        注意：需要去除pe为负(无意义)的
        """
        code = row["_id"]
        pes = []
        for col, val in zip(cols, row[cols].values):
            if val in ["", "-1"]:
                print(f"code {code} col {col} maybe not collect !!!")
                continue
            try:
                if float(val) > 0.:
                    pes.append(float(val))
            except:
                print(f"error code {code} col {col} val {val} cast float error !!!")
                continue
        import numpy as np
        if len(pes) == 0:
            print(f"code {code} pe data exception !!!")
            return 0
        try:
            quantile = np.quantile(pes, percent)
            quantile = round(quantile, 3)
            return quantile
        except Exception as e:
            print(f"{repr(e)}, code:{code}, pes:{pes} ")

    def g(self, query_code, name):
        """净利润同比增长率=(本期净利润-上年同期净利润)/上年同期净利润的绝对值*100%"""
        try:
            growth_list = []
            quarter_ = now_quarter()
            rs_growth = bs.query_growth_data(code=query_code, year=self.year, quarter=quarter_)
            while (rs_growth.error_code == '0') & rs_growth.next():
                growth_list.append(rs_growth.get_row_data())
            result = pd.DataFrame(growth_list, columns=rs_growth.fields)
            if result.shape[0] == 0:
                # 降级使用上一季度数据
                quarter_ -= 1
                rs_growth = bs.query_growth_data(code=query_code, year=self.year, quarter=quarter_)
                while (rs_growth.error_code == '0') & rs_growth.next():
                    growth_list.append(rs_growth.get_row_data())
                result = pd.DataFrame(growth_list, columns=rs_growth.fields)
            values_ = result["YOYNI"].tail(1).values[0]
            g = round(float(values_), 4)
            if g < 0:
                print("stock %s 第%d季度净利润同比增长率为负" % (name, quarter_))
            else:
                print("stock %s 第%d季度净利润同比增长率 = %s" % (name, quarter_, g))
        except Exception as e:
            print(repr(e))
            traceback.print_exc()
            return 0
        return g

    def peg(self, code, name):
        """PEG = 滚动市盈率 / 净利润同比增长率,如果分子或分母为零PEG=0"""
        peTTM = self.pe(code, name)
        g = self.g(code, name)
        if peTTM > 0 and g > 0:
            peg = round(peTTM / (100 * g), 4)
            print("stock %s PEG = %s" % (name, peg))
            return peg
        else:
            return 0

    def roe(self, query_code, name):
        """净资产收益率=归属母公司股东净利润/[(期初归属母公司股东的权益+期末归属母公司股东的权益)/2]*100%"""
        dupont_list = []
        quarter_ = now_quarter()
        try:
            rs_dupont = bs.query_dupont_data(code=query_code, year=self.year, quarter=quarter_)
            while (rs_dupont.error_code == '0') & rs_dupont.next():
                dupont_list.append(rs_dupont.get_row_data())
            result_profit = pd.DataFrame(dupont_list, columns=rs_dupont.fields)
            if result_profit.shape[0] == 0:
                # 降级使用上一季度数据
                quarter_ -= 1
                rs_dupont = bs.query_dupont_data(code=query_code, year=self.year, quarter=quarter_)
                while (rs_dupont.error_code == '0') & rs_dupont.next():
                    dupont_list.append(rs_dupont.get_row_data())
                result_profit = pd.DataFrame(dupont_list, columns=rs_dupont.fields)
            roe = round(float(result_profit["dupontROE"].tail(1).values[0]), 4)
            if roe < 0:
                print("stock %s 第%d季度净资产收益率为负" % (name, quarter_))
            else:
                print("stock %s 第%d季度净资产收益率=%s" % (name, quarter_, roe))
        except Exception as e:
            print(repr(e))
            traceback.print_exc()
            return 0
        return roe


def proportion_of_goodwill_net_assets(code):
    """商誉占净资产比率，就是商誉占企业合并报表中归属于母公司所有者权益的比例；大于10%有风险"""
    file = PROJ_HOME + '/data/商誉/沪深两市.csv'
    data = pd.read_csv(file, encoding="gbk")
    result = data[data['股票代码'] == int(code)]
    if result.shape[0] == 0:
        return 0
    else:
        return result['商誉占净资产比例'].values[0]


def cagr_percent(row, n, cur_value_col_name, base_value_col_name):
    """复合增长率=[(现有价值/基础价值)^(1/年数) - 1]*100
    归属于母公司所有者的净利润(万元)
    如果价值为负或者增长率为负，结果无意义返回None
    """
    if float(row[cur_value_col_name]) < 0 or float(row[base_value_col_name]) < 0:
        print("%s %s < 0 or %s < 0" % (row["_id"], cur_value_col_name, base_value_col_name))
        return None
    v = (float(row[cur_value_col_name]) / float(row[base_value_col_name])) ** (1.0 / n) - 1
    if v < 0:
        print("%s zzl < 0 " % (row["_id"]))
        return None
    return v * 100
